package com.demo2do.fms.admin.service.authority.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.demo2do.core.entity.exception.BusinessException;
import com.demo2do.core.entity.page.Page;
import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.persistence.annotation.Dao;
import com.demo2do.fms.admin.dao.authority.RoleDao;
import com.demo2do.fms.admin.dao.authority.UserDao;
import com.demo2do.fms.admin.dao.supplier.SupplierDao;
import com.demo2do.fms.admin.entity.search.authority.UserSearch;
import com.demo2do.fms.admin.handler.VamHandler;
import com.demo2do.fms.admin.service.DataServiceImpl;
import com.demo2do.fms.admin.service.authority.UserService;
import com.demo2do.fms.entity.authority.Organization;
import com.demo2do.fms.entity.authority.RoleTemplate;
import com.demo2do.fms.entity.authority.SupplierType;
import com.demo2do.fms.entity.authority.User;
import com.demo2do.fms.entity.authority.UserSupplierRelation;
import com.demo2do.fms.entity.supplier.common.Supplier;
import com.demo2do.fms.entity.supplier.common.Type;

/**
 * 
 * @author Ysy
 *
 */
@Service("userService")
public class UserServiceImpl extends DataServiceImpl<User> implements UserService {
    
    @Dao
    private UserDao userDao;
    
    @Dao
    private RoleDao roleDao;
    
    @Dao
    private SupplierDao supplierDao;
    
    @Autowired
    private GenericDaoSupport genericDaoSupport;
    
    @Autowired
    private VamHandler vamHandler;
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#get(java.lang.String)
     */
    public User load(String loginName) {
        return userDao.get(loginName);
    }
    
    /*
     * (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#count(com.demo2do.fms.entity.authority.RoleTemplate[])
     */
    public int count(RoleTemplate[] roleTemplates) {
        
        if(roleTemplates.length > 1) {
            return userDao.count(roleTemplates[0] + "%", roleTemplates[1] + "%");
        }
        
        return userDao.count(roleTemplates[0] + "%");
        
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#count(com.demo2do.fms.admin.entity.search.authority.UserSearch)
     */
    public int count(UserSearch search) {
    	
    	String sentence = search.buildSentenceTemplate();
        Map<String, Object> parameters = search.buildParameters();
        
        return genericDaoSupport.count(sentence, parameters);
    	
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#list(com.demo2do.fms.entity.supplier.common.Supplier)
     */
    public List<User> list(Supplier supplier) {
    	return userDao.list(supplier.getId());
    }
    
    /*
     * (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#list(com.demo2do.fms.entity.authority.RoleTemplate[], com.demo2do.core.entity.page.Page)
     */
    public List<User> list(RoleTemplate[] roleTemplates, Page page) {
        
        List<User> result = new ArrayList<User>();
        
        if(roleTemplates.length > 1){
            result =  userDao.list(roleTemplates[0] + "%", roleTemplates[1] + "%", page.getBeginIndex(), page.getEveryPage());
        } else {
            result =  userDao.list(roleTemplates[0] + "%", page.getBeginIndex(), page.getEveryPage());
        }
        
        page.calculate();
        return result;
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#list()
     */
    public List<User> list() {
        return userDao.list();
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#search(com.demo2do.fms.admin.entity.search.authority.UserSearch, com.demo2do.core.entity.page.Page)
     */
    @SuppressWarnings("unchecked")
	public List<User> search(UserSearch search, Page page) {
    	
    	// 1. build sentence
        String sentence = search.buildSentenceTemplate();
        Map<String, Object> parameters = search.buildParameters();
        
        // 2. do query
        List<User> users = genericDaoSupport.searchForList(sentence, parameters, page.getBeginIndex(), page.getEveryPage());
        page.calculate();
    	return users;
    	
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#existLoginName(java.lang.String)
     */
    public boolean existLoginName(String loginName) {
        return userDao.get(loginName) != null;
    }
    
    /*
     * (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#create(com.demo2do.fms.entity.authority.User)
     */
    public void create(User user, Long operator) {
    	
    	// 1. check user loginName
    	int existLoginName = userDao.countByLoginName(user.getLoginName());
    	if (existLoginName > 0) {
    		throw BusinessException.newInstance("400", "该登录名已存在");
    	}
    	
    	// 2. save user
        genericDaoSupport.save(user.initialize(operator));
        
    }
    
    /*
     * (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#create(com.demo2do.fms.entity.authority.User, java.util.List, java.lang.Long)
     */
    public void create(User user, List<Organization> organizations, Long operator) {
        
    	// 1. create user
        this.create(user, operator);
        
        // 2. create user_supplier_relation
        if(CollectionUtils.isNotEmpty(organizations)){
            
            for( Organization org : organizations ){
                genericDaoSupport.save(new UserSupplierRelation(user, SupplierType.ORGANIZATION, org.getId()));
            }
            
        }
        
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#createAdminUser(com.demo2do.fms.entity.authority.User, java.util.List, java.lang.Long)
     */
    public void createAdminUser(User user, List<Organization> organizations, Long operator) {
        
        // 1. create user
        this.create(user, operator);
        
        // 2. create user_supplier_relation
        if(CollectionUtils.isNotEmpty(organizations)) {
            
            for(Organization org : organizations) {
                genericDaoSupport.save(new UserSupplierRelation(user, SupplierType.ORGANIZATION, org.getId()));
            }
            
        }
        // 3. sysnc create vam user.
        if (user.isVam()) {
            vamHandler.createAdminOrBranch(user);
        }
        
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#createBranchUser(com.demo2do.fms.entity.authority.User, java.lang.Long)
     */
    public void createBranchUser(User user, Long operator) {
        
        // 1. check user loginName
        int existLoginName = userDao.countByLoginName(user.getLoginName());
        if (existLoginName > 0) {
            throw BusinessException.newInstance("400", "该登录名已存在");
        }
        
        // 2. save user
        genericDaoSupport.save(user.initialize(operator));
        
        // 3. sysnc create vam user.
        if (user.isVam()) {
            vamHandler.createAdminOrBranch(user);
        }
        
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#createFmsUser(com.demo2do.fms.entity.authority.User, java.lang.Long)
     */
    public void createFmsUser(User user, Long operator) {
        
        // 1. valid orgId
        if (user.getOrgId() == null) {
            throw BusinessException.newInstance("400", "请选择专属供应商");
        }
        
        // 2. valid required option, when user is vam_user
        Organization organization = genericDaoSupport.load(Organization.class, user.getOrgId());
        Supplier supplier = supplierDao.loadSupplier(user.getOrgId(), Type.MOTOR);
        
        if (supplier.isVam()) {
            if (user.getDepartmentId() == null) {
                throw BusinessException.newInstance("400", "请选择所属部门");
            }
            user.setVam(true);
        }
        
        // 3. create user
        this.create(user.initSupplierId(supplier.getId()), Arrays.asList(organization), operator);
        
        // 4. create remote_user
        if (user.isVam()) {
            vamHandler.create(user);
        }
        
    }
    
    /*
     * (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#createSponsorUser(com.demo2do.fms.entity.authority.User, java.lang.Long)
     */
    public void createSponsorUser(User user, Long operator) {
    		
        // 1. check supplierId
		if (user.getSupplierId() == null) {
			throw BusinessException.newInstance("400", "请选择所属一级供应商");
		}
		
		// 2. valid required option, when user is vam_user
		Supplier supplier = genericDaoSupport.load(Supplier.class, user.getSupplierId());
        if (supplier.isVam()) {
            if (user.getDepartmentId() == null) {
                throw BusinessException.newInstance("400", "请选择所属部门");
            }
            user.editVam(supplier.getOrgId());
        }
    	
        // 3. create user
    	this.create(user, operator);
    	
    	// 4. create remote_user
        if (user.isVam()) {
            vamHandler.create(user);
        }
        
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#createSupplierUser(com.demo2do.fms.entity.authority.User, java.lang.Long)
     */
    public void createSupplierUser(User user, Long operator) {
        
        // 1.1 check user loginName
        int existLoginName = userDao.countByLoginName(user.getLoginName());
        if (existLoginName > 0) {
            throw BusinessException.newInstance("400", "该登录名已存在");
        }
        
        // 2.2 check user whether has supplier
        Long supplierId = user.getSupplierId();
        if (supplierId == null) {
            throw BusinessException.newInstance("400", "请选择所属供应商");
        }
        
        // 3. check user whether valid when is vam-user
        Supplier supplier = genericDaoSupport.load(Supplier.class, supplierId);
        if (supplier.isVam()) {
            if (user.getDepartmentId() == null) {
                throw BusinessException.newInstance("400", "请选择所属部门");
            }
            user.editVam(supplier.getOrgId());
        }
        
        // 3. save user
        genericDaoSupport.save(user.initialize(operator));
        
        // 4. create remote_user
        if (user.isVam()) {
            vamHandler.create(user);
        }
        
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#edit(com.demo2do.fms.entity.authority.User)
     */
    public void edit(User user, Long operator) {
        
        // 1. update user
        genericDaoSupport.update(user.operator(operator, new Date()));
        
        // 2. sync vam
        if (user.isVam()) {
            vamHandler.edit(user);
        }
        
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#delete(com.demo2do.fms.entity.authority.User, java.lang.Long)
     */
    public void delete(User user, Long operator) {
        
        // 1. delete user
        genericDaoSupport.update(user.disable().operator(operator, new Date()));
        
        // 2. sync vam
        if (user.isVam()) {
            vamHandler.edit(user);
        }
        
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#resetPassword(com.demo2do.fms.entity.authority.User, java.lang.String)
     */
    public void resetPassword(User user, String password, Long operator) {
        genericDaoSupport.update(user.resetPassword(password).operator(operator, new Date()));
    }
    
    /*
     * (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#editOrganization(com.demo2do.fms.entity.authority.User, java.util.List)
     */
    public void editOrganization(User user, List<Long> organizations, Long operator) {
        
        // 1. delete all the old user_supplier_relations first
        userDao.deleteUserSupplierRelation(user);
        
        // 2. save all organizations user_supplier_relations
        if(CollectionUtils.isNotEmpty(organizations)){
            
           for(Long supplierId :organizations){
               genericDaoSupport.save(new UserSupplierRelation(user, SupplierType.ORGANIZATION, supplierId));
           }
           
        }
        
        // 3. update user
        genericDaoSupport.update(user.operator(operator, new Date()));
        
    }

    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#checkExistPassword(com.demo2do.fms.entity.authority.User, java.lang.String)
     */
    public boolean checkExistPassword(User user, String existPassword) {
        return user.checkExistPassword(existPassword);
    }
    
    /* (non-Javadoc)
     * @see com.demo2do.fms.admin.service.authority.UserService#editPassword(com.demo2do.fms.entity.authority.User, java.lang.String)
     */
    public void editPassword(User user, String password, Long operator) {
        genericDaoSupport.update(user.editPassword(password).operator(operator, new Date()));
    }

	/* (non-Javadoc)
	 * @see com.demo2do.fms.admin.service.authority.UserService#editAdminOrBranch(com.demo2do.fms.entity.authority.User, java.lang.Long)
	 */
	public void editAdminOrBranch(User user, Long operator) {
		
        // 1. update user
        genericDaoSupport.update(user.operator(operator, new Date()));
        
        // 2. sync vam
        if (user.isVam()) {
            vamHandler.editAdminOrBranch(user);
        }
		
	}

	/* (non-Javadoc)
	 * @see com.demo2do.fms.admin.service.authority.UserService#deleteAdminOrBranch(com.demo2do.fms.entity.authority.User, java.lang.Long)
	 */
	public void deleteAdminOrBranch(User user, Long operator) {
		
		// 1. delete user
        genericDaoSupport.update(user.disable().operator(operator, new Date()));
        
        // 2. sync vam
        if (user.isVam()) {
            vamHandler.editAdminOrBranch(user);
        }
		
	}

}
